package cn.mrcode.wxsdk.web.service;

import cn.mrcode.wxsdk.core.dialogue.common.exception.ReqException;
import cn.mrcode.wxsdk.core.dialogue.common.exception.WxException;
import cn.mrcode.wxsdk.core.dialogue.common.util.CastUtil;
import cn.mrcode.wxsdk.core.dialogue.service.BaseService;
import cn.mrcode.wxsdk.web.protocol.res.WebAccessTokenResData;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * 公用服务
 * @author zhuqiang
 * @version V1.0
 * @date 2015/9/18 11:42
 */
public class WebCommSV extends BaseService {
    private static Logger log = LoggerFactory.getLogger(WebCommSV.class);
    private static final  String ACCESS_TOKEN_API = "https://api.weixin.qq.com/sns/oauth2/access_token?";
    private static final String GRANT_TYPE = "authorization_code";

    /**
     * session key：微信网页授权code ： 该 code 只能被使用一次，所以处理规则如下：
     * 1.只要有需要openid的页面，就通过授权网页跳转，（考虑到不需要登录也需要openid的页面）<br/>
     * 2.获取到code 就存入session中 3. 调用code获取openid的方法处理：先查找 session是否有
     * openid(WX_SESSION_OPENID),无则需要通过获取code去获取openid，同时存入session中。
     * */
    public static final String WX_SESSION_AUTH_CODE_KEY = "WX_SESSION_AUTH_CODE_KEY";
    /** session key：openid ： **/
    public static final String WX_SESSION_OPENID_KEY = "WX_SESSION_OPENID_KEY";


    /**
     * 通过 授权 code 获取针对 openid 调用接口的 授权 accessToken 中的 openid
     * @param appId
     * @param appSecret
     * @param code
     * @return
     */
    public static String getOpenid(String appId, String appSecret, String code) throws ReqException, WxException {
        String url = ACCESS_TOKEN_API.concat("appid=").concat(appId)
                .concat("&secret=").concat(appSecret)
                .concat("&code=").concat(code)
                .concat("&grant_type=").concat(GRANT_TYPE);

            String resultJson = get(url);
            JSONObject resultObj = JSONObject.parseObject(resultJson);
            handerThrowErrcode(resultObj);
            WebAccessTokenResData wts = JSONObject.parseObject(resultJson, WebAccessTokenResData.class);
            return wts.getOpenid();
    }

    /**
     * <pre>
     *  提供一种获取维护openid的支持：会把处理的openid存放在session 和 request中 ，name= WX_SESSION_OPENID<br/>
     *  1. 通过授权跳转的请求调用本方法，将会自动判断session中是否存在code，不存在则通过code去获取，所以appId、appSecret必须不能为空
     *  2. 如果openid  和  code都为空则返回空串
     * </pre>
     * 1.
     * @param request 通过授权跳转请求的request请求对象
     * @param appId 必须填写
     * @param appSecret 必须存在
     * @return
     * @throws ReqException
     * @throws WxException
     */
    public static String getSessionOpenid(HttpServletRequest request, String appId, String appSecret) throws ReqException, WxException {
        String code = request.getParameter("code");
        return handerOpenidSetRequest(request, appId,appSecret,code);
    }

    /**
     * 获取session中的openid，前提是必须要在入口处调用过一次getSessionOpenid(HttpServletRequest request,String appId, String appSecret)方法，才能保证session中存在openid
     * @param request
     * @return 没有获取到则返回空字符串
     */
    public static String getSessionOpenid(HttpServletRequest request){
        Object openidObj = request.getSession().getAttribute(WX_SESSION_OPENID_KEY);
        return CastUtil.castString(openidObj);
    }

    /**
     * 存放和获取openid的处理
     * @param request
     * @param code
     */
    private static String handerOpenidSetRequest(HttpServletRequest request, String appId, String appSecret, String code) throws ReqException, WxException {
        HttpSession session = request.getSession();
        String openid = getSessionOpenid(request);
        if(StringUtils.isBlank(openid) && StringUtils.isNotBlank(code)){
            openid = WebCommSV.getOpenid(appId, appSecret, code);
            session.setAttribute(WX_SESSION_OPENID_KEY,openid);
            request.setAttribute(WX_SESSION_OPENID_KEY,openid);
        }
        return openid;
    }
}
